;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                ;;;
;;;                           cl-famix                             ;;;
;;;                     (Common Lisp FAMIX library)                ;;;
;;;                        by Adrian DOZSA                         ;;;
;;;                                                                ;;;
;;;                        MSE functionality                       ;;;
;;;                                                                ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;; cl-famix package
 
(in-package :cl-famix)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Printing model to MSE format

(defmethod print-to-mse ((model lisp-model) stream)
  (format stream "(Moose.Model (id: 1)")
  (when (name model)
    (format stream "~%   (name '~A')" (name model)))
  (format stream "~%   (entity")
  (loop for element in (sort-model-list-by-type (get-model-list model))
        when (complete-p element)
        do (print-to-mse element stream))
  (format stream ")~%   (sourceLanguage CommonLisp))"))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; Print to MSE functions

(defmethod print-to-mse ((element FAMIX.ModelRoot) stream)
  (format stream "~%      (~A " (type-name element)))
  
(defmethod print-to-mse :after ((element FAMIX.ModelRoot) stream)
  (format stream "(id: ~A)" (id element))
  (format stream "~%         (stub ~A)" (stub element)))

(defmethod print-to-mse :after ((element FAMIX.AbstractObject) stream)
  (format stream "~%         (isExpanded ~A)" (isExpanded element)))

(defmethod print-to-mse :after ((element FAMIX.AbstractNamedEntity) stream)
  (format stream "~%         (name '~A')" (name element)))

(defmethod print-to-mse :after ((element FAMIX.AbstractBehaviouralEntity) stream)
  (when (belongsTo element)
    (format stream "~%         (belongsTo (idref: ~D))" (belongsTo element)))
  (when (not (zerop (nosexp element)))
    (format stream "~%         (NOSEXP ~D)" (nosexp element)))
  (when (not (zerop (nomesexp element)))
    (format stream "~%         (NOMESEXP ~D)" (nomesexp element)))
  (when (source element)
    (format stream "~%         (sourceAnchor '~A')" (substitute #\" #\' (write-to-string (source element)))))
  (when (signature element)
    (format stream "~%         (signature '~A')" (signature element))))

(defmethod print-to-mse :after ((element FAMIX.AbstractCallableEntity) stream)
  )

(defmethod print-to-mse :after ((element FAMIX.Function) stream)   
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.GenericFunction) stream) 
  (when (methodCombination element)
    (format stream "~%         (methodCombination '~A')" (methodCombination element)))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.Method) stream)
  (format stream "~%         (specializedOn")
  (loop for id in (specializedOn element)
        do (format stream " (idref: ~D)" id))
  (format stream ")")
  (format stream "~%         (specializes (idref: ~D))" (specializes element))
  (when (qualifier element)
    (format stream "~%         (qualifier '~A')" (qualifier element)))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.AbstractTransformationEntity) stream)
  )

(defmethod print-to-mse :after ((element FAMIX.Macro) stream)
  (when (macroFunction element)
    (format stream "~%         (macroFunction '~A')" (substitute #\" #\' (write-to-string (macroFunction element)))))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.AbstractScopable) stream)
  )

(defmethod print-to-mse :after ((element FAMIX.Class) stream)
  (when (metaclass element)
    (format stream "~%         (metaclass ~A)" (metaclass element)))
  (when (source element)
    (format stream "~%         (sourceAnchor '~A')" (substitute #\" #\' (write-to-string (source element)))))
  (when (belongsTo element)
    (format stream "~%         (belongsTo (idref: ~D))" (belongsTo element)))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.Namespace) stream)
  (when (uses element)
    (format stream "~%         (uses")
    (loop for id in (uses element)
          do (format stream " (idref: ~D)" id))
    (format stream ")"))
  (when (imports element)
    (format stream "~%         (imports")
    (loop for id in (imports element)
          do (format stream " (idref: ~D)" id))
    (format stream ")"))
  (when (exports element)
    (format stream "~%         (exports")
    (loop for id in (exports element)
          do (format stream " (idref: ~D)" id))
    (format stream ")"))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.AbstractStructuralEntity) stream)
  (when (declaredClass element)
    (format stream "~%         (declaredClass (idref: ~D))" (declaredClass element)))
  (when (declaredType element)
    (format stream "~%         (declaredType (idref: ~D))" (declaredType element))))

(defmethod print-to-mse :after ((element FAMIX.AbstractLocalEntity) stream)
  (format stream "~%         (belongsTo (idref: ~D))" (belongsTo element)))

(defmethod print-to-mse :after ((element FAMIX.LocalVariable) stream)  
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.FormalParameter) stream)
  (format stream "~%         (position ~D)" (positionInList element))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.GlobalVariable) stream)  
  (when (belongsTo element)
    (format stream "~%         (belongsTo (idref: ~D))" (belongsTo element)))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.Attribute) stream)
  (format stream "~%         (hasClassScope ~A)" (hasClassScope element))
  (format stream "~%         (belongsTo (idref: ~D))" (belongsTo element))
  (when (reader element)
    (format stream "~%         (reader '~A')" (reader element)))
  (when (writer element)
    (format stream "~%         (writer '~A')" (writer element)))
  (when (accessor element)
    (format stream "~%         (accessor '~A')" (accessor element)))
  (when (initform element)
    (format stream "~%         (initform '~A')" (initform element)))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.AbstractFile) stream)
  )

(defmethod print-to-mse :after ((element FAMIX.File) stream)
  (when (belongsTo element)
    (format stream "~%         (belongsTo (idref: ~D))" (belongsTo element)))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.Folder) stream)
  (when (belongsTo element)
    (format stream "~%         (belongsTo (idref: ~D))" (belongsTo element)))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.Comment) stream)
  (format stream "~%         (content ~A)" (content element))
  (format stream "~%         (belongsTo (idref: ~D))" (belongsTo element))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.AbstractAssociation) stream)
  )

(defmethod print-to-mse :after ((element FAMIX.Access) stream)
  (format stream "~%         (accesses (idref: ~D))" (accesses element))
  (format stream "~%         (readWriteAccess ~A)" (readWriteAccess element))
  (format stream "~%         (accessedIn (idref: ~D))" (accessedIn element))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.Invocation) stream)
  (when (receivingVariable element)
    (format stream "~%         (receivingVariable (idref: ~D))" (receivingVariable element)))
  (format stream "~%         (invokedBy (idref: ~D))" (invokedBy element))
  (format stream "~%         (candidate (idref: ~D))" (candidate element))
  (when (invokes element)
    (format stream "~%         (invokes '~A')" (invokes element)))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.InheritanceDefinition) stream)
  (format stream "~%         (subclass (idref: ~D))" (subclass element))
  (format stream "~%         (superclass (idref: ~D))" (superclass element))
  (format stream "~%         (index ~D)" (index element))
  (format stream ")"))

(defmethod print-to-mse :after ((element FAMIX.MacroExpansion) stream)
  (format stream "~%         (expandsTo (idref: ~D))" (expandsTo element))
  (format stream "~%         (macro (idref: ~D))" (macro element))
  (format stream ")"))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;